#ifndef Quaternion_h__
#define Quaternion_h__

#include "Vectors.h"
#include "Matrix.h"

namespace math
{
	class Quaternion 
	{
	public:
		float w, x, y, z;
		Quaternion(float fw = 1.0, float fx = 0.0f, float fy = 0.0f, float fz = 0.0f) {
			w = fw; x = fx; y = fy; z = fz;
		}

		Quaternion(const Matrix& rot) {
			FromRotationMatrix(rot);
		}

		Quaternion(float fAngle, const Vector3& vAxis) {
			FromAngleAxis(fAngle, vAxis);
		}

		Quaternion(const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis) {
			FromAxes(xAxis, yAxis, zAxis);
		}

		Quaternion& operator=(const Quaternion& rQt) {
			w = rQt.w; x = rQt.x; y = rQt.y; z = rQt.z;
			return *this;
		}
		
		bool operator== (const Quaternion& rhs) const {
			return rhs.x == x && rhs.y == y && rhs.z == z && rhs.w == w;
		}

		bool operator!= (const Quaternion& rhs) const {
			return !operator==(rhs);
		}

		void    FromRotationMatrix(const Matrix& mRot);
		void    FromAngleAxis(float fAngle, const Vector3& vAxis);
		void    FromAxes(const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis);

		Matrix  ToRotationMatrix() const;
		void    ToRotationMatrix(Matrix& mRot) const;
		void    ToAngleAxis(float& fAngle, Vector3& vAxis) const;
		void    ToAxes(Vector3& xAxis, Vector3& yAxis, Vector3& zAxis);

		Vector3 XAxis() const;
		Vector3 YAxis() const;
		Vector3 ZAxis() const;
		
		Quaternion operator+ (const Quaternion& rQt) const;
		Quaternion operator- (const Quaternion& rQt) const;
		Quaternion operator* (const Quaternion& rQt) const;
		Quaternion operator* (float fScalar) const;
		Vector3    operator* (const Vector3& rkVector) const;
		Quaternion operator- () const;

		float      DotProduct(const Quaternion& rhs) const ;
		float      Length();
		void       Normalize();
		Quaternion Inverse() const;

		

	public:
		static Quaternion Slerp(const Quaternion& p, const Quaternion& q, float t);
		static Quaternion Conjugate(const Quaternion& q);
		static Quaternion Power(const Quaternion&q, float fExponent);
	};

	

}

#endif // Quaternion_h__
